﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using BridgeShips;
using UnityEngine;


namespace Framework.Entity
{
    /// <summary>
    /// 实体管理器
    /// </summary>
    public class EntityManager : IEntityManager, IModule
    {
        private LinkedList<IEntity> m_Entitys = null;

        public LinkedList<IEntity>  Entitys() {
                return m_Entitys;
        }

        public void AddEntity(IEntity entity)
        {
            if (entity == null) return;
            LinkedListNode<IEntity> node = m_Entitys.First;
            
            while(node != null)
            {
                if (node.Value.Priority > entity.Priority)
                    break;
                node = node.Next;
            }
            entity.OnStart();
            
            if (node==null)
            {
                m_Entitys.AddFirst(new LinkedListNode<IEntity>(entity));
            }
            else
            {
                m_Entitys.AddBefore(node, entity);
            }
        }

        public  void LerpForwardLocalRotation(Transform curTrans, Quaternion quatTarget,float factor = 45.0f, float factor1 = 1.0f)
        {
            float angle = Quaternion.Angle(curTrans.localRotation, quatTarget);
            angle = Mathf.Clamp(angle, 0.0f, factor);
            float detal = Mathf.Sin(Mathf.Deg2Rad * angle) * 0.1f;
            detal = Mathf.Clamp(detal, -0.25f, 0.25f);
            curTrans.localRotation = Quaternion.Lerp(curTrans.localRotation, quatTarget, Time.time * detal );
           // UnityEngine.Debug.LogError("LerpForwardLocalRotation");
        }

        public void LerpForwardLocalRotation(Transform curTrans, Vector3 targetForward, float factor0 = 45.0f, float factor1 = 1.0f)
        {
            Quaternion quatCurFarward = Quaternion.LookRotation(curTrans.forward, Vector3.up);
            Quaternion quatTarFarward = Quaternion.LookRotation(targetForward, Vector3.up);

            float angle = Quaternion.Angle(quatCurFarward, quatTarFarward);
            angle = Mathf.Clamp(angle, 0.0f, factor0);
            float detal = Mathf.Sin(Mathf.Deg2Rad * angle) * factor1;
            detal = Mathf.Clamp(detal, 0.0f, 0.25f) ;
            curTrans.localRotation = Quaternion.Lerp(quatCurFarward, quatTarFarward, Time.time * detal * 0.1f);
           // UnityEngine.Debug.LogError("LerpForwardLocalRotation");
        }

        public float LerpPosition(Transform curTrans, Vector3 targetPosition, float factor0 = 10.0f,float factor1 = 1.0f)
        {
            targetPosition.y = curTrans.position.y;
            float fRemainDistance =  (targetPosition - curTrans.position).magnitude;
            float tempFactor = Mathf.Clamp(fRemainDistance / 2, factor0 * 0.1f, factor0);
            //  tempFactor = Mathf.Sin(tempFactor * Mathf.Deg2Rad) * factor1 + 0.01f;
            tempFactor = Mathf.Abs(Mathf.Sin(fRemainDistance * Mathf.Deg2Rad)) + 0.1f;
            if (fRemainDistance < 0.15f)
                tempFactor = 1.0f;
            Vector3 tempPosition = Vector3.Lerp(curTrans.position, targetPosition, Time.deltaTime * tempFactor*0.5f);
            tempPosition.y = 7.0f;
            curTrans.position = tempPosition;
            return fRemainDistance;
        }


            public Transform ObjTransform(uint shipID)
        {
            var entity = Get(shipID);
            if(entity != null)
            {
                return entity.Get().transform;
            }
            return null;
        }
        public void RemoveEntity(IEntity entity)
        {
            if (entity == null) return;
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null)
            {
                if (node.Value == entity)
                {
                    m_Entitys.Remove(node);
                    break;
                }
            }
        }
        public void ShowEntity(IEntity entity)
        {
            if (entity == null) return;
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null)
            {
                if (node.Value == entity)
                {
                    node.Value.OnShow();
                    break;
                }
            }
        }

        public IEntity Get(uint id) {
            if (id <= 0) return null;
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null) {
                if (node.Value.GetID() == id) {
                    return node.Value;
                }
                node = node.Next;
            }
            return null;
        }

        public void HideEntity(IEntity entity)
        {
            if (entity == null) return;
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null)
            {
                if (node.Value == entity)
                {
                    node.Value.OnHide();
                    break;
                }
            }
        }
        public int Priority
        {
            get
            {
                return ModulePriority.EntityPriority;
            }
        }
        public void Init()
        {
            m_Entitys = new LinkedList<IEntity>();
            
        }
        public void Destroy()
        {
            LinkedListNode<IEntity> node = m_Entitys.First;
            while(node != null)
            {
                node.Value.OnRelease();
                node = node.Next;
            }
        }

        public void Update(float frameTime, float realTime)
        {
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null)
            {
                IEntity entity = node.Value;
                if (entity.IsShow)
                    entity.OnUpdate(frameTime, realTime);
                node = node.Next;
            }
        }
        public void Reset()
        {
            LinkedListNode<IEntity> node = m_Entitys.First;
            while (node != null)
            {
                node.Value.OnRelease();
                node = node.Next;
            }
        }
    }
}
